#include "lib.h"

inline void list_init(st_list *list) {
	list->next = list;
	list->prev = list;
}

inline void list_add_to_behind(st_list *entry, st_list *new) {
    new->next = entry->next;
    entry->next = new;
    new->prev = entry;
    new->next->prev = new;
}

inline void list_add_to_before(st_list *entry, st_list *new) {
    new->prev = entry->prev;
    new->next = entry;
    new->prev->next = new;
    entry->prev = new;
}

inline void list_del(st_list *entry) {
    entry->prev->next = entry->next;
    entry->next->prev = entry->prev;
}

inline long list_is_empty(st_list *entry) {
    if (entry == entry->next && entry->prev == entry) {
        return 1;
    } else {
        return 0;
    }
}

inline st_list *list_prev(st_list *entry) {
    return entry->prev;
}

inline st_list *list_next(st_list *entry) {
    return entry->next;
}

inline int strlen(char *str) {
    register int __res;
	__asm__	__volatile__	(	"cld	\n\t"		// 清空DF标志
					"repne	\n\t"					// 当cx != 0和ZF标志位为0时重复执行字符串指令
					"scasb	\n\t"					// al - [es:edi]，ecx = ecx - 1，并设置ZF标志位
					"notl	%0	\n\t"				// %n表示占位符，n表示第几个参数，按位取反得到正整数
					"decl	%0	\n\t"				// ecx = ecx - 1，得到字符串长度
					:"=c"(__res)					// =表示输出操作数，c表示将输入变量放入ecx
					:"D"(str),"a"(0),"0"(0xffffffff)	// "D"表示将变量放入edi，"a"表示将变量放入eax，这里eax=0，"0"表示第0个参数设置为-1，即ecx=-1
					:
				);
	return __res;
}

inline void *memset(void *addr, unsigned char c, long count) {
    int d0, d1;
    unsigned long tmp = c * 0x0101010101010101UL;
    __asm__ __volatile__(
        "cld \n\t"
        "rep \n\t"
        "stosq \n\t"
        "testb $4, %b3 \n\t"
        "je	1f \n\t"
        "stosl \n\t"
        "1:\ttestb $2, %b3 \n\t"
        "je	2f\n\t"
        "stosw \n\t"
        "2:\ttestb $1, %b3 \n\t"
        "je	3f \n\t"
        "stosb \n\t"
        "3: \n\t"
        :"=&c"(d0),"=&D"(d1)
        :"a"(tmp),"q"(count),"0"(count/8),"1"(addr)	
        :"memory"
    );
    return addr;
}

inline void *memcpy(void *from, void *to, long count) {
    int d0, d1, d2;
    __asm__ __volatile__(
        "cld \n\t"
        "rep \n\t"
        "movsq \n\t"
        "testb $4, %b4 \n\t"
        "je	1f \n\t"
        "movsl \n\t"
        "1:\ttestb $2, %b4 \n\t"
        "je	2f\n\t"
        "movsw \n\t"
        "2:\ttestb $1, %b4 \n\t"
        "je	3f \n\t"
        "movsb \n\t"
        "3: \n\t"
        :"=&c"(d0), "=&D"(d1), "=&S"(d2)
        :"0"(count/8), "q"(count), "1"(to), "2"(from)	
        :"memory"
    );
    return to;
}

inline unsigned char io_in8(unsigned short port) {
    unsigned char ret = 0;
    __asm__ __volatile__ (
        "inb %%dx, %0 \n\t"
        "mfence \n\t"
        :"=a"(ret)
        :"d"(port)
        :"memory"
    );
    return ret;
}

inline unsigned int io_in32(unsigned short port) {
    unsigned int ret = 0;
    __asm__ __volatile__ (
        "inl %%dx, %0 \n\t"
        "mfence \n\t"
        :"=a"(ret)
        :"d"(port)
        :"memory"
    );
    return ret;
}

inline void io_out8(unsigned short port, unsigned char value) {
    __asm__ __volatile__ (
        "outb %0, %%dx \n\t"
        "mfence \n\t"
        :
        :"a"(value), "d"(port)
        :"memory"
    );
}

inline void io_out32(unsigned short port, unsigned int value) {
    __asm__ __volatile__ (
        "outl %0, %%dx \n\t"
        "mfence \n\t"
        :
        :"a"(value), "d"(port)
        :"memory"
    );
}

inline void wrmsr(unsigned long addr, unsigned long value) {
    __asm__ __volatile__ ("wrmsr \n\t"::"d"(value >> 32), "a"(value & 0xffffffff), "c"(addr):"memory");
}